package particle;

import processing.core.*;

public class Particle {
	final PVector home;
	PVector loc;
	PVector vel;
	PVector acc;
	boolean force_home;
	float r;
	float timer;
	int update;
	PVector[][] magneticField;
	public int color;
	int velo_height;
	boolean inUserArray;
	int calcintervall;
	PVector last_loc;
	double sinPart;
	double cosPart;
	double angleIndex;

	// Another constructor (the one we are using here)
	Particle(PVector l, PVector[][] magneticField) {
		home = l.get();
		inUserArray = false;
		acc = new PVector(/* 0.005F,0.01F,0 */0, 0);
		vel = new PVector(/* -0.01F, 0.5F, 0 */0, 0);
		loc = l.get();
		r = 2.0F;
		timer = (float) ((Math.random()) * 90 + 60);
		this.magneticField = magneticField;
		color = 0xFFFFFFFF;
		velo_height = 0;
		calcintervall = 0;
	}

	// Method to update location
	public void update() {
		calcintervall++;

		if (force_home) {
			PVector dest = PVector.sub(home, loc);
			vel.set(0, 0, 0);
			dest.mult(0.05f);
			loc.add(dest);
			return;
		}

		if (calcintervall % 30 == 0) {
			calcintervall = 0;

			float rand_vel = (float) ((Math.random() - 0.5) * 0.2);
			float rand_vel2 = (float) ((Math.random() - 0.5) * 0.2);
			vel.add(rand_vel, rand_vel2, 0);
			// vel.add( new PVector( (float)Math.cos(angleIndex),
			// (float)Math.sin(angleIndex) ));
			// angleIndex+= (Math.PI*2)/720.0;
			// if(angleIndex > Math.PI*2) angleIndex = 0;

		}

		int dist_x = (int) Math.abs(loc.x - magneticField.length / 2);
		int dist_y = (int) Math.abs(loc.y - magneticField[0].length / 2);
		double max_radius = Math.sqrt(magneticField.length / 2
				* magneticField.length / 2 + magneticField[0].length / 2
				* magneticField[0].length / 2);
		double euk = Math.sqrt(dist_x * dist_x + dist_y * dist_y);
		double percent_dist = euk / max_radius;
		PVector center = new PVector(magneticField.length / 2,
				magneticField[0].length / 2);
		PVector subtract = PVector.sub(center, loc);
		subtract.mult((float) percent_dist * 0.5f);

		PVector tmp_add = PVector.add(loc, vel);
		if (tmp_add.x >= magneticField.length
				|| tmp_add.y >= magneticField[0].length || tmp_add.x < 15
				|| tmp_add.y < 0) {
			loc.set(new PVector((float) Math.random()
					* (magneticField.length - 1), (float) Math.random()
					* (magneticField[0].length - 1)));
			inUserArray = true;
			vel.normalize();
			vel.mult(-1);
			color = 0xFF000000;
		} else {
			loc.add(vel);
		}

		if (loc.x > 0 || loc.y > 0 || loc.x < magneticField.length
				|| loc.y < magneticField[0].length) {
			loc.add(magneticField[(int) loc.x][(int) loc.y]);
		}

		vel.mult(0.98f);

		velo_height = 2;
		last_loc = loc;
	}

	private void force_add(PVector magnet, boolean againstMagnetic) {
		PVector force;
		float diff_x = magnet.x - loc.x;
		float diff_y = magnet.y - loc.y;

		if (Math.abs(diff_x) > 1 && Math.abs(diff_y) > 1) {
			double angle = Math.atan2((diff_y), (diff_x)) * 180 / Math.PI;

			int x_offs = getx_Polar(3, angle);
			int y_offs = gety_Polar(3, angle);

			if (againstMagnetic == false) {
				force = new PVector(x_offs, y_offs);
			} else {
				force = new PVector(-x_offs, -y_offs);
			}

			loc.add(force);

		} else {
			loc.set(home);
		}
	}

	public void force_home() {
		force_home = true;
	}

	public void force_disable_home() {
		force_home = false;
	}

	private int getx_Polar(double radius, double angle) {
		return (int) (radius * (Math.cos(angle / 360 * 2 * Math.PI)));
	}

	private int gety_Polar(double radius, double angle) {
		return (int) (radius * (Math.sin(angle / 360 * 2 * Math.PI)));
	}

}